package com.hzw.saas.service.rss.service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import javax.annotation.Resource;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hzw.saas.api.rss.IJournalArticleService;
import com.hzw.saas.api.rss.ILibraryCatalogService;
import com.hzw.saas.api.rss.ILibraryService;
import com.hzw.saas.api.rss.bo.LibraryBO;
import com.hzw.saas.api.rss.bo.LibraryCatalogBO;
import com.hzw.saas.api.rss.query.JournalArticleFavQuery;
import com.hzw.saas.api.storage.IResourceFileService;
import com.hzw.saas.common.config.util.AssertUtil;
import com.hzw.saas.common.config.util.PageParam;
import com.hzw.saas.common.util.MapperUtil;
import com.hzw.saas.common.util.SnowFlakeUtil;
import com.hzw.saas.service.rss.mapper.LibraryCatalogMapper;
import com.hzw.saas.service.rss.model.LibraryCatalog;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
@Service("libraryCatalogServiceImpl")
public class LibraryCatalogServiceImpl extends ServiceImpl<LibraryCatalogMapper, LibraryCatalog> implements ILibraryCatalogService, IService<LibraryCatalog> {

    @Resource(name = "libraryService")
    private ILibraryService libraryService;
    @Resource(name = "journalArticleService")
    private IJournalArticleService journalArticleService;
    @Resource
    private IResourceFileService resourceFileService;
    private final LibraryCatalogMapper libraryCatalogMapper;

    @Override
    public List<LibraryCatalogBO> initCatalog(String userId) {
        List<LibraryCatalogBO> userTree = findUserCatalog("00000");
        if (CollectionUtil.isEmpty(userTree)){
            return Collections.emptyList();
        }
        ArrayList<LibraryCatalogBO> libraryCatalogBOS1 = new ArrayList<>();

        userTree.forEach(libraryCatalogBO -> {
            String pid = SnowFlakeUtil.nextIdStr();
            libraryCatalogBO.setPid(pid);
            libraryCatalogBO.setCreatorId(userId);
            libraryCatalogBO.setEditorId(userId);
            libraryCatalogBOS1.add(libraryCatalogBO);
            if (CollectionUtil.isNotEmpty(libraryCatalogBO.getLibraryCatalogBOS())){
                List<LibraryCatalogBO> libraryCatalogBOS = libraryCatalogBO.getLibraryCatalogBOS();
                libraryCatalogBOS.forEach(libraryCatalogBO1 -> {
                    libraryCatalogBO1.setParentId(pid);
                    libraryCatalogBO1.setPid(SnowFlakeUtil.nextIdStr());
                    libraryCatalogBO1.setCreatorId(userId);
                    libraryCatalogBO1.setEditorId(userId);
                    libraryCatalogBOS1.add(libraryCatalogBO1);
                });
            }
        });
        saveBatch(libraryCatalogBOS1);
        return userTree;
    }

    @Override
    public void addCatalog(LibraryCatalogBO libraryCatalogBO) {
        if(Objects.isNull(libraryCatalogBO)) {
            return;
        }
        String parentId = libraryCatalogBO.getParentId();
        confirmLevel(parentId);
        LibraryCatalog map = MapperUtil.nf().map(libraryCatalogBO, LibraryCatalog.class);
        map.setPid(SnowFlakeUtil.nextIdStr());
        map.setType(2);
        if (map.getParentId().equals("0") || map.getParentId() == null || map.getParentId().equals("")){
            map.setLevel(1);
        } else {
            LibraryCatalog byId = this.getById(map.getParentId());
            map.setLevel(byId.getLevel()+1);
        }
        this.save(map);
    }

    /**
     * 层级校验，最多两级
     * @param parentId
     */
    void confirmLevel(String parentId){
        if(StrUtil.isBlank(parentId) || Objects.equals("0", parentId) ) {
            return;
        }
        List<LibraryCatalog> list = this.lambdaQuery().eq(LibraryCatalog::getPid, parentId).list();
        AssertUtil.assertThrow(parentId +"找不到父节点" , CollectionUtil.isEmpty(list));
        LibraryCatalog libraryCatalog = list.get(0);
        AssertUtil.assertThrow("分类层级最多两级", libraryCatalog.getLevel()>=2);
    }
    @Override
    public void saveBatch(List<LibraryCatalogBO> libraryCatalogBOS){
        if (CollectionUtil.isEmpty(libraryCatalogBOS)) {
            return;
        }
        List<LibraryCatalog> libraryCatalogs = MapperUtil.nf().mapAsList(libraryCatalogBOS, LibraryCatalog.class);
        libraryCatalogs.forEach(libraryCatalog -> {
            if (StrUtil.isBlank(libraryCatalog.getPid())){
                libraryCatalog.setPid(SnowFlakeUtil.nextIdStr());
            }
        });
        this.saveBatch(libraryCatalogs);
    }

    @Override
    public void updateCatalog(LibraryCatalogBO libraryCatalogBO) {
        if (null != libraryCatalogBO){
            AssertUtil.assertThrow("找不到主键", libraryCatalogBO.getPid() == null || "".equals(libraryCatalogBO.getPid()));
            String parentId = libraryCatalogBO.getParentId();
            confirmLevel(parentId);
            LibraryCatalog map = MapperUtil.nf().map(libraryCatalogBO, LibraryCatalog.class);
            this.updateById(map);
        }
    }

    @Override
    @Transactional
    public void deleteCatalog(String pid) {
        if (StrUtil.isBlank(pid)) {
            return;
        }
        LibraryCatalog libraryCatalogParent = getById(pid);
        confirmType(libraryCatalogParent.getPid());

        //如果是父节点，先清理子节点
        String parentId = libraryCatalogParent.getParentId();
        if ( StrUtil.isBlank(parentId) || parentId.equals("0")){
            List<LibraryCatalog> libraryCatalogs = this.lambdaQuery().eq(LibraryCatalog::getParentId, libraryCatalogParent.getPid()).list();
            if (CollectionUtil.isNotEmpty(libraryCatalogs)) {
                List<String> catalogIds = libraryCatalogs.stream().map(LibraryCatalog::getPid).collect(Collectors.toList());
                removeByIds(catalogIds);
                // 删除该分类下的所有文献资源
                for (LibraryCatalog libraryCatalog : libraryCatalogs) {
                    removeLibraryResourceByCatalog(libraryCatalog);
                }
            }
        } else {
            // 选择的是子节点
            removeLibraryResourceByCatalog(libraryCatalogParent);
        }
        this.removeById(pid);
    }

    private void removeLibraryResourceByCatalog(LibraryCatalog libraryCatalog) {
        IPage<LibraryBO> libraries = libraryService.list(PageParam.getBigPageParam(), libraryCatalog.getCreatorId(), libraryCatalog.getPid(), null);
        libraries.getRecords().forEach(library -> {
            Integer type = library.getType();
            if(Objects.equals(1, type)) {
                // 取消收藏文献
                JournalArticleFavQuery articleFavQuery = new JournalArticleFavQuery();
                articleFavQuery.setArticleId(library.getPid());
                articleFavQuery.setFav(0);
                articleFavQuery.setLibraryCatalogId("1");
                articleFavQuery.setUserId(libraryCatalog.getCreatorId());
                journalArticleService.collectArticle(articleFavQuery);
            } else if(Objects.equals( 0, type)) {
                // 上传文献
                resourceFileService.deleteFile(library.getDownloadUrl());
            }
        });
        // 删除所有文献
        libraryService.deleteBatch(libraries.getRecords().stream().map(LibraryBO::getPid).collect(Collectors.toList()));
    }

    @Override
    public List<LibraryCatalogBO> findUserCatalog(String userId) {
        List<LibraryCatalog> list = this.lambdaQuery().eq(LibraryCatalog::getCreatorId, userId).list();
        if (CollectionUtil.isEmpty(list)){
            return Collections.emptyList();
        }
        List<LibraryCatalogBO> libraryCatalogBOS = MapperUtil.nf().mapAsList(list, LibraryCatalogBO.class);
        return buildTree(libraryCatalogBOS, "0");
    }

    @Override
    public boolean findHistory(String userId) {
        if (StrUtil.isBlank(userId)){
            return true;
        }
        List<LibraryCatalog> history = libraryCatalogMapper.findHistory(userId);
        if (CollectionUtil.isEmpty(history)){
            return false;
        }
        return true;
    }

    private static LibraryCatalogBO findChildren(LibraryCatalogBO treeNode, List<LibraryCatalogBO> treeNodes) {
        for (LibraryCatalogBO it : treeNodes) {
            if (treeNode.getPid().equals(it.getParentId())) {
                if (treeNode.getLibraryCatalogBOS() == null) {
                    treeNode.setLibraryCatalogBOS(new ArrayList<>());
                }
                treeNode.getLibraryCatalogBOS().add(findChildren(it, treeNodes));
            }
        }
        return treeNode;
    }


    public  List<LibraryCatalogBO> buildTree(List<LibraryCatalogBO> treeNodes, String parentId) {
        List<LibraryCatalogBO> trees = new ArrayList();
        for (LibraryCatalogBO treeNode : treeNodes) {
            if (parentId.equals("0")) {
                if (parentId.equals(treeNode.getParentId())) {
                    trees.add(findChildren(treeNode, treeNodes));
                }
            } else {
                if (parentId.equals(treeNode.getPid())) {
                    trees.add(findChildren(treeNode, treeNodes));
                }
            }

        }
        return trees;
    }

    @Override
    public void confirmLibraryCatalog(String catalogId){
        if (StrUtil.isNotBlank(catalogId)){
            LibraryCatalog libraryCatalog = this.getById(catalogId);
            AssertUtil.assertThrow("只能在二级目录下新增文献",null == libraryCatalog || libraryCatalog.getParentId() == null || libraryCatalog.getParentId().equals("") || libraryCatalog.getParentId().equals("0"));
        }else {
            AssertUtil.assertThrow("请传入正确的分类节点", StrUtil.isBlank(catalogId));
        }

    }

    private void confirmType(String treeNode){
        if (StrUtil.isNotBlank(treeNode)){
            LibraryCatalog byId = this.getById(treeNode);
            AssertUtil.assertThrow("系统分类不可以删除",byId.getType() == 1);
        }else {
            AssertUtil.assertThrow("请传入正确的分类节点", StrUtil.isBlank(treeNode));
        }
    }
    @Override
    public LibraryCatalogBO findById(String pid){
        if (StrUtil.isNotBlank(pid)){
            LibraryCatalog byId = this.getById(pid);
            return MapperUtil.nf().map(byId, LibraryCatalogBO.class);
        }
        return null;
    }

    @Override
    public LibraryCatalogBO findFavByUser(String userId) {
        if (StrUtil.isNotBlank(userId)){
            List<LibraryCatalog> list = this.lambdaQuery().eq(LibraryCatalog::getCreatorId, userId)
                .eq(LibraryCatalog::getType, 1)
                .list();
            if (CollectionUtil.isNotEmpty(list)){
                return MapperUtil.nf().map(list.get(0), LibraryCatalogBO.class);
            }
        }
        return null;
    }

    @Override
    public List<LibraryCatalogBO> getByIds(List<String> ids) {
        if (CollectionUtil.isEmpty(ids)){
            return Collections.emptyList();
        }
        List<LibraryCatalog> list = this.lambdaQuery().in(LibraryCatalog::getPid,ids).list();
        return MapperUtil.nf().mapAsList(list,LibraryCatalogBO.class);
    }
}
